#include <QColor>
#include <QGridLayout>
#include <QStringList>
#include <QPushButton>
#include <botan/secmem.h>
#include <botan/hash.h>
#include <users/user.h>
#include <login_and_registration/logindialog.h>
#include <login_and_registration/registrationdialog.h>

#include "utils/functions.h"

namespace login_and_registration {

LoginDialog::LoginDialog(users::usersList &list, QWidget *parent) :
	list(list), QDialog(parent)
{
		// set up the layout
	auto* formGridLayout = new QGridLayout( this );

	// initialize the username combo box so that it is editable
	comboUsername = new QComboBox( this );
	comboUsername->setEditable( true );
	connect(comboUsername, &QComboBox::currentIndexChanged, this, &LoginDialog::resetCounter);
	// initialize the password field so that it does not echo
	// characters
	editPassword = new QLineEdit( this );
	editPassword->setEchoMode( QLineEdit::PasswordEchoOnEdit );

	// initialize the labels
	labelUsername = new QLabel( this );
	labelPassword = new QLabel( this );
	labelUsername->setText( tr( "Логин" ) );
	labelUsername->setBuddy( comboUsername );
	labelPassword->setText( tr( "Пароль" ) );
	labelPassword->setBuddy( editPassword );
	labelUserCorrect = new QLabel(this);
	labelUserCorrect->setVisible(false);
	labelUserCorrect->setStyleSheet("QLabel {color : red;}");

	// initialize buttons
	buttons = new QDialogButtonBox( this );
	addUserButton = new QPushButton("Добавить пользователя", this);
	closeButton = new QPushButton("Завершить программу", this);
	buttons->addButton(addUserButton, QDialogButtonBox::ApplyRole);
	buttons->addButton(QDialogButtonBox::Ok );
	buttons->addButton(closeButton, QDialogButtonBox::ApplyRole);
	buttons->button(QDialogButtonBox::Ok )->setText("Войти");

	// connects slots
	connect(buttons->button( QDialogButtonBox::Ok ),
			SIGNAL (clicked()), this, SLOT (slotAcceptLogin()) );

	connect(addUserButton,
			SIGNAL (clicked()), this, SLOT (addUser()));

	connect( closeButton,
		SIGNAL (clicked()), this, SLOT (reject()));


	// place components into the dialog
	formGridLayout->addWidget( labelUsername, 0, 0 );
	formGridLayout->addWidget( comboUsername, 0, 1 );
	formGridLayout->addWidget( labelPassword, 1, 0 );
	formGridLayout->addWidget( editPassword, 1, 1 );
	formGridLayout->addWidget(labelUserCorrect, 2,1);
	formGridLayout->addWidget( buttons, 3, 0, 1, 3 );

	setLayout( formGridLayout );
	if (!list.empty()) {
		for(const auto& user : list) {
			comboUsername->addItem(QString::fromStdString(user._login));
		}
	}
	setWindowTitle( tr("Вход в программу") );
	setModal( true );
}


void LoginDialog::setUsername(QString &username){
	bool found = false;
	for( int i = 0; i < comboUsername->count() && ! found ; i++ )
		if( comboUsername->itemText( i ) == username ) {
			comboUsername->setCurrentIndex( i );
			found = true;
		}

	if( ! found ){
		int index = comboUsername->count();
		comboUsername->addItem( username );

		comboUsername->setCurrentIndex( index );
	}

	// place the focus on the password field
	editPassword->setFocus();
}


void LoginDialog::setPassword(QString &password){
	editPassword->setText( password );
}


void LoginDialog::slotAcceptLogin(){
	if (!list.empty()) {
		QString username = comboUsername->currentText();
		int index = comboUsername->currentIndex();
		auto hasedPass = utils::generateSymmetricKeyFromPassword(editPassword->text().toStdString()
		                                                         +list[index]._salt, 32);

		if(username.toStdString() == list[index]._login && list[index].compare_hashes(hasedPass)) {
			labelUserCorrect->setVisible(false);
			emit acceptLogin(list[index]);
			done(1);
		} else {
			counter++;
			labelUserCorrect->setVisible(true);
			auto trys = 3-counter;
			labelUserCorrect->setText("Введен неверный логин или пароль. Осталось " +
				QString::number(trys) + (trys == 2 ? " попытки" : " попытка"));
			if (counter >=3) {
				done(-1);
			}
		}
	}
}

void LoginDialog::resetCounter() {
	counter = 0;
	labelUserCorrect->setVisible(false);
}

void LoginDialog::addUser() {
	registrationDialog dialog(this);
	dialog.show();
	dialog.setModal(true);
	connect(&dialog, &registrationDialog::sendUser, &list, &users::usersList::appendUser);
	dialog.exec();
	if (!list.empty()) {
		comboUsername->clear();
		for(const auto& user : list) {
			comboUsername->addItem(QString::fromStdString(user._login));
		}
	}
}
}
